/*
 * Copyright (c) 2018-2999 九五云信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 */


package com.yami.shop.service.impl;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.yami.shop.bean.app.dto.StationSalesDto;
import com.yami.shop.bean.enums.OfflineHandleEventStatus;
import com.yami.shop.bean.enums.OfflineHandleEventType;
import com.yami.shop.bean.enums.StationEnum;
import com.yami.shop.bean.model.OfflineHandleEvent;
import com.yami.shop.bean.model.Station;
import com.yami.shop.bean.param.OfflineHandleEventAuditParam;

import com.yami.shop.bean.param.StationDetailParam;
import com.yami.shop.bean.param.TimeParam;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.Arith;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.dao.StationMapper;
import com.yami.shop.service.StationService;
import com.yami.shop.service.OfflineHandleEventService;
import lombok.AllArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.*;

/**
 * 自提点
 *
 * @author YXF
 * @date 2020-04-23 15:18:29
 */
@Service
@AllArgsConstructor
public class StationServiceImpl extends ServiceImpl<StationMapper, Station> implements StationService {

    private final StationMapper stationMapper;

    private final PasswordEncoder passwordEncoder;

    private final OfflineHandleEventService offlineHandleEventService;

    @Override
    public IPage<Station> getPage(PageParam<Station> page, Station station) {
        return stationMapper.getPage(page,station);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditApply(Long eventId, Long handleId, String reapplyReason) {
        // 更新活动为待审核状态
        stationMapper.updateStatus(handleId, StationEnum.WAIT_AUDIT.getValue());

        // 更新事件状态
        offlineHandleEventService.updateToApply(eventId, reapplyReason);
    }

    @Override
    public IPage<StationDetailParam> getStationList(Double lat, Double lng, String stationName, Long shopId, String userId, Page page) {
        IPage<StationDetailParam> stationPage = stationMapper.getStationList(page, lat, lng,stationName, shopId,null);
        List<StationDetailParam> stationList = stationPage.getRecords();
        //获取常用的自提点
        StationDetailParam defaultStation = stationMapper.selectGoOften(userId,shopId);
        if(defaultStation != null) {
            IPage<StationDetailParam> stationDetailParamIPage = stationMapper.getStationList(page,lat, lng,"", shopId,defaultStation.getStationId());
            List<StationDetailParam> stationParams = stationDetailParamIPage.getRecords();
            StationDetailParam stationParam = stationParams.get(0);
            stationParam.setDefaultStation(1);
            stationList.add(stationParam);
        }
        for (StationDetailParam stationParam : stationList){
            double distance = stationParam.getDistance() ;
//            distance = Arith.div(distance,1000,2);
//            if (distance.length()>5){
//                distance = distance.substring(0,distance.length()-5)+"."+distance.substring(distance.length()-5,distance.length()-4);
//            }else if(distance.length()<4){
//                distance = "0.1";
//            }else {
//                distance = "0." + distance.substring(0,1);
//            }
            stationParam.setDistance(distance);
            String timeDate = stationParam.getTimeDate();
            StationDetailParam.timeDateModeVO timeDateModeVO = new Gson().fromJson(timeDate, StationDetailParam.timeDateModeVO.class);
            List<TimeParam> timeParams = new ArrayList<>();
            Long[] shopTime = timeDateModeVO.getShopTime();
            int startHour = DateUtil.hour(new Date(shopTime[0]),true);
            int endHour = DateUtil.hour(new Date(shopTime[1]),true);
            String startTime = DateUtil.format(new Date(shopTime[0]),"HH:mm");
            String endTime = DateUtil.format(new Date(shopTime[1]),"HH:mm");
            List<String> hourTimes = Lists.newArrayList();
            Date startStationTime = DateUtil.offsetDay(new Date(), Integer.valueOf(timeDateModeVO.getStationStartTime()));
            Date endStationTime = DateUtil.offsetDay(startStationTime,Integer.valueOf(timeDateModeVO.getStationEndTime()));
            String currentTime = DateUtil.format(new Date(),"HH:mm");
            int currentHour = DateUtil.hour(startStationTime,true);
            int currentMinute = DateUtil.minute(startStationTime);
            if (Integer.valueOf(timeDateModeVO.getStationStartTime()).equals(0) && endHour < currentHour){
                startStationTime = DateUtil.offsetDay(startStationTime, 1);
            }else {
                if (timeDateModeVO.getInterval().equals(2) && Integer.valueOf(timeDateModeVO.getStationStartTime()).equals(0) && endHour > currentHour){
                    hourTimes = getBusinessByNoon(currentHour, endHour, currentTime, endTime);
                    timeParams.add(new TimeParam(DateUtil.format(startStationTime,"MM-dd"),hourTimes));
                    startStationTime = DateUtil.offsetDay(startStationTime,1);
                }else if (timeDateModeVO.getInterval().equals(3)){
                    hourTimes = getBusinessByHour(currentHour, endHour, currentMinute, DateUtil.minute(new Date(shopTime[1])));
                    timeParams.add(new TimeParam(DateUtil.format(startStationTime,"MM-dd"),hourTimes));
                    startStationTime = DateUtil.offsetDay(startStationTime,1);
                }else if (timeDateModeVO.getInterval().equals(4)){
                    hourTimes = getBusinessByHalfHour(currentHour, endHour,currentMinute, DateUtil.minute(new Date(shopTime[1])));
                    timeParams.add(new TimeParam(DateUtil.format(startStationTime,"MM-dd"),hourTimes));
                    startStationTime = DateUtil.offsetDay(startStationTime,1);
                }
            }
            while (startStationTime.getTime() <= endStationTime.getTime()){
                if (timeDateModeVO.getInterval().equals(1)){
                    List<String> hourTimeList = Lists.newArrayList();
                    hourTimeList.add(startHour + ":00-" + endHour + ":00");
                    timeParams.add(new TimeParam(DateUtil.format(startStationTime,"MM-dd"),hourTimeList));
                }else if (timeDateModeVO.getInterval().equals(2)){
                    hourTimes = getBusinessByNoon(startHour, endHour, startTime, endTime);
                    timeParams.add(new TimeParam(DateUtil.format(startStationTime,"MM-dd"),hourTimes));
                }else if (timeDateModeVO.getInterval().equals(3)){
                    hourTimes = getBusinessByHour(startHour, endHour, DateUtil.minute(new Date(shopTime[0])), DateUtil.minute(new Date(shopTime[1])));
                    timeParams.add(new TimeParam(DateUtil.format(startStationTime,"MM-dd"),hourTimes));
                }else if (timeDateModeVO.getInterval().equals(4)){
                    hourTimes = getBusinessByHalfHour(startHour, endHour, DateUtil.minute(new Date(shopTime[0])), DateUtil.minute(new Date(shopTime[1])));
                    timeParams.add(new TimeParam(DateUtil.format(startStationTime,"MM-dd"),hourTimes));
                }
                startStationTime = DateUtil.offsetDay(startStationTime,1);
            }
            stationParam.setTimeParams(timeParams);
            stationParam.setBusiness(startTime+ "-"+ endTime);
        }
        return stationPage;
    }

    /**
     * 获取上中下午取货时间列表
     * @param startHour  开始时间（小时）
     * @param endHour   结束时间（小时）
     * @param startTime 营业开始时间
     * @param endTime 营业结束时间
     * @return
     */
    private List<String> getBusinessByNoon(int startHour, int endHour,String startTime,String endTime) {
        String morning = "早上";
        String noon = "下午";
        String night = "晚上";
        List<String> hourTime = Lists.newArrayList();
        if (startHour < 12){
            if (endHour > 18){
                hourTime.add(morning + "(" + startTime + "-12:00)");
                hourTime.add(noon + "(12:00-18:00)");
                hourTime.add(night + "(18:00-" + endTime + ")");
            }else if (endHour >12){
                hourTime.add(morning + "(" + startTime + "-12:00)");
                hourTime.add(noon + "(12:00-18:00)");
            }else {
                hourTime.add(morning + "(" + startTime + "-" + endTime + ")");
            }
        }else if (startHour >= 12 && startHour < 18){
            if (endHour > 18){
                hourTime.add(noon + "(" + startTime + "-18:00)");
                hourTime.add(night + "(18:00-" + endTime + ")");
            }else {
                hourTime.add(night + "(" + startTime + "-" + endTime + ")");
            }
        }else if(startHour >= 18){
            hourTime.add(night + "(" + startTime + "-" + endTime + ")");
        }
        return hourTime;
    }

    private List<String> getBusinessByHour(int startHour, int endHour, int startMinute, int endMinute) {
        String startMinuteStr = "";
        String endMinuteStr = "";
        if (startMinute < 10){
            startMinuteStr = "0" + startMinute;
        }else {
            startMinuteStr = startMinuteStr + startMinute;
        }
        if (endMinute < 10){
            endMinuteStr = "0" + endMinute;
        }else {
            endMinuteStr = endMinuteStr + endMinute;
        }

        List<String> hourTime = Lists.newArrayList();
        int hour = startHour;
        if (startHour == endHour){
            hourTime.add(startHour + ":" + startMinuteStr + "-" + endHour + ":"+ endMinuteStr);
        }
        if (startMinute > 0){
            hourTime.add(startHour + ":" + startMinuteStr + "-" + ++hour + ":00");
        }
        while (hour < endHour){
            hourTime.add(hour + ":00-" + ++hour + ":00");
        }
        if (endMinute > 0){
            hourTime.add(hour + ":00-" + hour + ":" + endMinuteStr);
        }
        return hourTime;
    }

    private List<String> getBusinessByHalfHour(int startHour, int endHour, int startMinute, int endMinute) {
        String startMinuteStr = "";
        String endMinuteStr = "";
        if (startMinute < 10){
            startMinuteStr = "0" + startMinute;
        }else {
            startMinuteStr = startMinuteStr + startMinute;
        }
        if (endMinute < 10){
            endMinuteStr = "0" + endMinute;
        }else {
            endMinuteStr = endMinuteStr + endMinute;
        }

        List<String> hourTime = Lists.newArrayList();
        int hour = startHour;
        if (startHour == endHour && startMinute < endMinute){
            hourTime.add(startHour + ":" + startMinuteStr + "-" + endHour + ":"+ endMinuteStr);
        }
        if (startMinute > 0 && startMinute <30){
            hourTime.add(startHour + ":" + startMinuteStr + "-" + hour + ":30");
        }else if (startMinute >= 30){
            hourTime.add(startHour + ":30-" + ++hour + ":00");
        }
        while (hour < endHour){
            hourTime.add(hour + ":00-" + hour + ":30");
            hourTime.add(hour + ":30-" + ++hour + ":00");
        }
        if (endMinute > 0 && endHour <30){
            hourTime.add(hour + ":00-" + hour + ":" + endMinuteStr);
        }else if (endHour >= 30){
            hourTime.add(hour + ":00-" + hour + ":30");
            hourTime.add(hour + ":30-" + hour + ":" + endMinuteStr);
        }
        return hourTime;
    }


    @Override
    public void offline(Station station, String offlineReason, Long sysUserId) {
        // 添加下线处理记录
        Date now = new Date();
        OfflineHandleEvent offlineHandleEvent = new OfflineHandleEvent();
        offlineHandleEvent.setShopId(station.getShopId());
        offlineHandleEvent.setHandleId(station.getStationId());
        offlineHandleEvent.setHandleType(OfflineHandleEventType.STATION.getValue());
        offlineHandleEvent.setOfflineReason(offlineReason);
        offlineHandleEvent.setCreateTime(now);
        offlineHandleEvent.setHandlerId(sysUserId);
        offlineHandleEvent.setStatus(OfflineHandleEventStatus.OFFLINE_BY_PLATFORM.getValue());
        offlineHandleEvent.setUpdateTime(now);
        offlineHandleEventService.save(offlineHandleEvent);

        // 更新活动状态为下线
        stationMapper.updateStatus(station.getStationId(), StationEnum.OFFLINE.getValue());
    }

    @Override
    public void auditSeckill(OfflineHandleEventAuditParam offlineHandleEventAuditParam, Long sysUserId) {
        // 审核通过
        if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            // 更新秒杀活动为正常状态
            stationMapper.updateStatus(offlineHandleEventAuditParam.getHandleId(), StationEnum.NORMAL.getValue());
        }
        // 审核不通过
        else if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            stationMapper.updateStatus(offlineHandleEventAuditParam.getHandleId(), StationEnum.AUDIT_FAIL.getValue());
        }
        // 更新审核时间
        offlineHandleEventService.auditOfflineEvent(offlineHandleEventAuditParam, sysUserId);
    }

    @Override
    @Cacheable(cacheNames = "station", key = "#stationId")
    public Station getStationInfoById(Long stationId) {
        Station stationInfoById = stationMapper.getStationInfoById(stationId);
        return stationInfoById;
    }

    @Override
    public Station getStationInfoByAccount(String account) {
        return stationMapper.getStationInfoByAccount(account);
    }

    @Override
    public List<StationSalesDto> getStationSalesRecord(Long shopId, Long stationId) {
        Date day = DateUtil.beginOfDay(new Date());
        Date month = DateUtil.beginOfMonth(day);
        List<StationSalesDto> stationSalesDtoList = stationMapper.getStationSalesRecord(shopId, stationId,day,month);
        for (StationSalesDto stationSalesDto: stationSalesDtoList){
            stationSalesDto.setPayAmount(Arith.add(stationSalesDto.getActualTotal(),stationSalesDto.getPlatformAmount()));
            if (stationSalesDto.getUserNum()==0.0){
                continue;
            }
            stationSalesDto.setCustomerUnitPrice(Arith.div(stationSalesDto.getPayAmount(),stationSalesDto.getUserNum(),2));
        }
        return stationSalesDtoList;
    }

    @Override
    @CacheEvict(cacheNames = "station", key = "#station.stationId")
    public int insertStation(Station station) {
        Date date = new Date();
        station.setCreateTime(date);
        station.setUpdateTime(date);
        return stationMapper.insert(station);
    }

    @Override
    @CacheEvict(cacheNames = "station", key = "#station.stationId")
    public int updateStation(Station station) {
        Station stationDB = stationMapper.selectById(station.getStationId());
        station.setUpdateTime(new Date());
        //自提点地址、电话改变，则更新tz_order_self_station表中对应的地址、电话
        String addr =null;
        Boolean addrChange = !stationDB.getProvinceId().equals(station.getProvinceId()) || !stationDB.getCityId().equals(station.getCityId()) ||
                !stationDB.getAreaId().equals(station.getAreaId()) || !StrUtil.equals(stationDB.getAddr(),station.getAddr());
        if(addrChange){
            addr = station.getProvince() + station.getCity() + station.getArea() + station.getAddr();
            stationMapper.changeStationAddr(station.getStationId(),addr, null);

        }
        String phone = null;
        Boolean phoneChange = !StrUtil.equals(stationDB.getPhone(),station.getPhone()) || !StrUtil.equals(stationDB.getPhonePrefix(),station.getPhonePrefix());
        if(phoneChange){
            phone = StrUtil.isNotBlank(station.getPhonePrefix())?station.getPhonePrefix() + "-":"";
            phone = phone + station.getPhone();
        }
        if (addrChange || phoneChange){
            stationMapper.changeStationAddr(station.getStationId(),addr, phone);
        }
        return stationMapper.updateById(station);
    }
    @Override
    @CacheEvict(cacheNames = "station", key = "#station.stationId")
    public void changeAccountInfo(Station station) {
        int count = stationMapper.getCountByAccount(station.getAccount().trim(),station.getStationId());
        if (count > 0){
            // 此账号已存在，请输入新的账号
            throw new YamiShopBindException("yami.station.account.exist");
        }
        Station stationNew = new Station();
        stationNew.setStationId(station.getStationId());
        stationNew.setAccount(station.getAccount());
        stationNew.setPassword(passwordEncoder.encode(station.getPassword()));
        stationMapper.updateById(stationNew);
    }

    @Override
    public int getCountByAccount(String account, Long stationId) {
        return stationMapper.getCountByAccount(account.trim(),stationId);
    }

    @Override
    @CacheEvict(cacheNames = "station", key = "#stationId")
    public int removeStationById(Long stationId) {
        return stationMapper.deleteById(stationId);
    }

    @Override
    @CacheEvict(cacheNames = "station", key = "#stationId")
    public void removeCacheByStationId(Long stationId) {

    }
}
